package com.thx.common.web.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;

import javax.servlet.http.HttpServletRequest;

/**
 * 用户 IP 相关工具类.
 *
 * @author balance
 */
public final class IpUtil {

  private IpUtil() {

  }

  /**
   * 获取用户的真实IP地址, 当访问地址为localhost时地址格式为 0:0:0:0:0:0:1, 为127.0.0.1时正常.
   */
  public static String realityIp(final HttpServletRequest request) {
    if (request == null) {
      throw new IllegalArgumentException("request 不能为空");
    }

    String realIp = request.getHeader("x-forwarded-for ");
    if (!StringUtils.isEmpty(realIp)) {
      while (!StringUtils.isEmpty(realIp)
          && realIp.equals("unknown ")) {
        realIp = request.getHeader("x-forwarded-for ");
      }
    }
    if (StringUtils.isEmpty(realIp) || realIp.equals("unknown ")) {
      realIp = request.getHeader("Proxy-Client-IP ");
    }
    if (StringUtils.isEmpty(realIp) || realIp.equals("unknown ")) {
      realIp = request.getHeader("WL-Proxy-Client-IP ");
    }
    if (StringUtils.isEmpty(realIp) || realIp.equals("unknown ")) {
      realIp = request.getRemoteAddr();
    }
    return realIp;
  }

  /**
   * 获取用户的最后一次代理IP.
   */
  public static String proxyIp(HttpServletRequest request) {
    if (request == null) {
      return null;
    }
    String realIp = realityIp(request);
    if (!StringUtils.isEmpty(realIp)
        && !realIp.equalsIgnoreCase(request.getRemoteAddr())) {
      return request.getRemoteAddr();
    }
    return null;
  }

  /**
   * 根据ip获取用户的真实地址.
   */
  public static String getAddressByIp(String ip) {
    try {
      String address = "";
      String jsonStr = getJsonContent("http://ip.taobao.com/service/getIpInfo.php?ip=" + ip);
      if (StringUtils.isNotBlank(jsonStr)) {
        JSONObject obj = JSON.parseObject(jsonStr);
        Integer code = (Integer) obj.get("code");
        if (code == 0) {
          JSONObject date = obj.getJSONObject("data");

          String country = (String) date.get("country");
          if (StringUtils.isNotBlank(country)) {
            address += country;
          }

          String area = (String) date.get("area");
          if (StringUtils.isNotBlank(area)) {
            address += area;
          }

          String region = (String) date.get("region");
          if (StringUtils.isNotBlank(region)) {
            address += region;
          }

          String city = (String) date.get("city");
          if (StringUtils.isNotBlank(city)) {
            address += city;
          }

          String county = (String) date.get("county");
          if (StringUtils.isNotBlank(county)) {
            address += county;
          }

          String isp = (String) date.get("isp");
          if (StringUtils.isNotBlank(isp)) {
            address += isp;
          }
        } else {
          address = "IP地址有误";
        }
        return address;
      }
    } catch (RuntimeException ex) {
      return null;
    }
    return null;
  }

  /**
   * 调用淘宝ip接口获取返回的json内容.
   */
  private static String getJsonContent(String urlStr) {
    try {
      URL url = new URL(urlStr);
      HttpURLConnection httpConn = (HttpURLConnection) url
          .openConnection();
      httpConn.setConnectTimeout(3000);
      httpConn.setReadTimeout(3000);
      httpConn.setDoInput(true);
      httpConn.setRequestMethod("GET");
      httpConn.connect();
      int respCode = httpConn.getResponseCode();
      if (respCode == 200) {
        return convertStream2Json(httpConn.getInputStream());
      } else {
        return null;
      }
    } catch (IOException ex) {
      return null;
    }
  }

  /**
   * 将获取的输入流转化为json字符串.
   */
  private static String convertStream2Json(InputStream in) throws IOException {
    try {
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      int temp;
      byte[] buf = new byte[1024];
      while ((temp = in.read(buf)) != -1) {
        out.write(buf, 0, temp);
      }
      return new String(out.toByteArray(), Charset.forName("utf-8"));
    } finally {
      if (in != null) {
        IOUtils.closeQuietly(in);
      }
    }
  }

}
